/*
 * modsAX Javascript Library
 * modsAX.com 2009 squall
 * modsAX are licensed under a Creative Commons Attribution 3.0 license.
 * http://creativecommons.org/licenses/by/3.0/deed.ko
 * If you don't want to author Link
 * You must register. Join the modsAX license member then you free use modsAX
 * http://www.modsAX.com
 */

jQuery.fn.autoComplete = function(arg){
  var myInput = new modsInput();
  arg.inputID = this.get(0).id;
  myInput.setConfig(arg);
  return this;
};

var modsInput = Class.create(modsAX, {
  version       : "modsInput V1.0",
  author        : "SQUALL",
  createDate    : "2010.01.08",
  lastModifyDate: "2010.04.25",
  initialize: function($super){
    $super();
    this.config.options = [];
    this.config.containerClassName = "modsInput";
    this.config.containerHeight = 150;
    this.config.inputType = "open"; //static
    this.config.arrow = false; // true
    this.config.zindex = 100;
    this.active = false;
    this.positioning = false; // if you need repositioning then this.positioning = false;
    this.otherClick;
    this.coverA = "href=\"#modsExceptionScript\"";
    this.config.easing = {
      open:{duration:300, easing:"bounceOut"}, 
      close:{duration:300, easing:"expoInOut"}
    };
    this.config.inputErrorMsg = "입력할 수 없습니다.";
  },
  /* ------------------------------------------------------------------------------------------------------------------ */
  /* init ~~~~~~ */
  init: function(){
    var onkeyup = this.onkeyup.bind(this);
    if(mods.browser.browser == "ie" && mods.browser.version == 6){
    jQuery("#"+this.config.inputID).bind("keyup", onkeyup);
    }else{
    jQuery("#"+this.config.inputID).bind("keydown", onkeyup);
    }

    this.initContainerPin();

    this.container = jQuery("<div class=\"inputList\" id=\""+this.config.inputID+"_container\"></div>");
    var listOnMouseDown = this.listOnMouseDown.bind(this);
    this.container.bind("mousedown", listOnMouseDown);

    if(this.config.arrow) this.initArrow();

    // option array sortBy text
    this.config.options = this.config.options.sort(function(a, b){
      return a.text > b.text;
    });
  },
  initContainerPin: function(){
    this.containerPin = jQuery("<div id=\""+this.config.inputID+"_containerPin\" class=\""+this.config.containerClassName+"\"></div>");
    //this.containerPin.css({"border":"1px solid"});
    var iobj = jQuery("#"+this.config.inputID);
    iobj.before(this.containerPin);

    var offSetParent = iobj.offsetParent();
    var bt = 0;
    var bl = 0;
    try{
      bt = offSetParent.css("border-top-width").number();
    }catch(e){}
    try{
      bl = offSetParent.css("border-left-width").number();
    }catch(e){}

    var offSet = iobj.position();
    var offBox = {width:iobj.outerWidth(), height:iobj.outerHeight(true)};

    var mybr = mods.browser.browser;
    var brver = mods.browser.version;
    
    if(mybr == "ie" && brver == 6){
      this.containerPin.css({"top":(offSet.top+bt)+"px"});
    }else if(mybr == "ie" && brver == 7){
      //this.containerPin.css({"top":(offSet.top-bt)+"px"});
    }else{
      this.containerPin.css({left:(offSet.left)+"px", "top":(offSet.top)+"px"});
    }
    this.containerPin.css({"width":offBox.width+"px"});
  },
  initArrow: function(){
    /* arrow positioning */
    this.arrow = jQuery("<a "+this.coverA+" id=\""+this.config.inputID+"_arrow\" class=\"inputArrow\">select</a>");
    this.containerPin.append(this.arrow);
    var iobj = jQuery("#"+this.config.inputID);

    var offBox = {width:iobj.outerWidth(true), height:iobj.outerHeight(true)};
    this.arrow.css({right:"0px", top:"0px", height:(offBox.height)+"px"});

    var activeContainer = this.activeContainer.bind(this);
    this.arrow.bind("click", activeContainer);
    var onkeyup = this.onkeyup.bind(this);
    this.arrow.bind("keydown", onkeyup);
  },
  showError: function(msg){
    var errorMsg = jQuery("<div class=\"inputError\">"+msg+"</div>");
    this.containerPin.append(errorMsg);
    var iobj = jQuery("#"+this.config.inputID);
    var offBox = {width:iobj.outerWidth(true), height:iobj.outerHeight(true)};
    errorMsg.css({left:"0px", top:(offBox.height)+"px", width:(offBox.width)-2+"px", height:(offBox.height)+"px"});
    errorMsg.fadeIn().delay(500).fadeOut();
  },
  setOptions: function(opts){
    this.config.options = opts;
  },
  /* ------------------------------------------------------------------------------------------------------------------ */
  /* on observe method ~~~~~~ */
  onkeyup: function(event){
    if(event.keyCode == mods.Event.KEY_RETURN){
      if(this.observer) clearTimeout(this.observer);
      if(this.stedix != undefined){
        jQuery("#"+this.config.inputID).val( this.config.options[this.stedix].text );
        this.deActiveContainer();
      }
      event.stopPropagation();
      return;
    }

    if(event.keyCode == mods.Event.KEY_TAB){
      return;
    }

    if(this.active){
      if(event.keyCode == mods.Event.KEY_DOWN){
        if(this.observer) clearTimeout(this.observer);
        this.focusMove(1);
      }
      if(event.keyCode == mods.Event.KEY_UP){
        if(this.observer) clearTimeout(this.observer);
        this.focusMove(-1);
      }
    }

    if(this.observer) clearTimeout(this.observer);
    
    var onKeyupAct = this.onKeyupAct.bind(this);
    this.observer = setTimeout(function(){
      onKeyupAct(event.keyCode);
    }, 300);
  },
  onKeyupAct: function(keyCode){ // choose key action and input value;
    var seWord = jQuery("#"+this.config.inputID).val();

    if(keyCode == mods.Event.KEY_ESC){
      this.deActiveContainer();
      return;
    }
    if(keyCode == mods.Event.KEY_DOWN){
      if(!this.active){
        this.activeContainer();
        if(seWord != "") this.focusWord(mods.consonantKR(seWord));
      }
      return;
    }
    if(keyCode == mods.Event.KEY_UP){
      if(!this.active){
        this.activeContainer();
        if(seWord != "") this.focusWord(mods.consonantKR(seWord));
      }
      return;
    }

    if(seWord == ""){
      this.deActiveContainer();
    }else{
      if(!this.active) this.activeContainer();
      //focus word
      this.focusWord(mods.consonantKR(seWord));
    }
  },
  onOtherClick: function(event){
    var eA = event.target;
    var ids = [this.config.inputID, this.config.inputID+"_arrow"];
    var result = ids.or(function(n){return n == eA.id});
    if(result) return;
    this.deActiveContainer();
  },
  listOnMouseDown: function(event){
    var tg = this.container[0].id;
    if(event.target.tagName != "A") return;
    var el = event.target;
    if(!el.id) return;
    var seq = el.id.replace(tg+"_", "");
    jQuery("#"+this.config.inputID).val( this.config.options[seq].text );
    this.stedix = seq;
  },
  /* ------------------------------------------------------------------------------------------------------------------ */
  /* class method ~~~~~~ */
  activeContainer: function(){
    //modsInput container init
    if(this.active){
      this.deActiveContainer();
      return;
    }else{
      this.active = true;
    }
    if(this.arrow) this.arrow.addClass("sted");

    this.container.html(this.getPrintList());
    this.containerPin.append(this.container);
    this.containerPin.css({"zIndex":"99999"});
    this.otherClick = this.onOtherClick.bind(this);
    jQuery(document).bind("click", this.otherClick);
    if(!this.positioning) this.setPosition();
    
    this.container.css({"display":"none"});
    this.container.slideDown({duration:this.config.easing.open.duration, easing:this.config.easing.open.easing});
  },
  deActiveContainer: function(){
    this.active = false;
    if(this.arrow) this.arrow.removeClass("sted");
    try{
      this.container.slideUp({duration:this.config.easing.close.duration, easing:this.config.easing.close.easing});
      this.containerPin.css({"zIndex":""});
    }catch(e){}
    if(this.otherClick) jQuery(document).unbind("click", this.otherClick);
    if(this.observer) clearTimeout(this.observer);
    if(this.config.inputType == "static"){
      //input value static;
      var seWord = jQuery("#"+this.config.inputID).val();
      var result = this.config.options.or(function(n){
        return n.text == seWord;
      });
      if(!result){
        if(seWord != "") this.showError(this.config.inputErrorMsg);
        jQuery("#"+this.config.inputID).val("");
        this.stedix = undefined;
      }
    }
    if(this.config.onupdate){
      if(this.stedix != undefined){
        this.config.onupdate({id:this.config.inputID, value:this.config.options[this.stedix].value, text:jQuery("#"+this.config.inputID).val()});
      }else{
        this.config.onupdate({id:this.config.inputID, value:"", text:jQuery("#"+this.config.inputID).val()}); 
      }
    }
  },
  setPosition: function(){
    var iobj = jQuery("#"+this.config.inputID);
    var absSet = iobj.offset();
    var offBox = {width:iobj.outerWidth(true), height:iobj.outerHeight()};
    var dimParent = {width:document.body.scrollWidth, height:document.body.scrollHeight}; //offSetParent.getDimensions(); //
    if(document.body.clientHeight > dimParent.height) dimParent.height = document.body.clientHeight;

    var containerHeight = this.config.containerHeight;
    var containerWidth = offBox.width-2;
    var containerTop = offBox.height;
    var dimContainer = {width:this.container.outerWidth(), height:this.container.outerHeight()};
    //container height control
    (dimContainer.height > containerHeight) ? containerHeight = this.config.containerHeight : containerHeight = dimContainer.height;

    var containerBottom = absSet.top + containerHeight + offBox.height;
    if(dimParent.height < containerBottom) containerTop = containerTop - containerHeight - offBox.height;

    var styles = {};
    styles.top = containerTop+"px";
    styles.height = containerHeight+"px";
    styles.width = containerWidth+"px";
    this.container.css(styles);

    this.positioning = true;
  },
  getPrintList: function(){
    var tg = this.container[0].id;
    var coverA = this.coverA;
    var po = [];
    po.push("<div id=\""+tg+"_lists\">");
    jQuery.each(this.config.options, function(index, n){
      po.push("<a "+coverA+" id=\""+tg+"_"+index+"\">"+n.text+"</a>");
    });
    po.push("</div>");
    return po.join('');
  },
  focusWord: function(sw){
    var tg = this.container[0].id;
    eval("var reAt= /^"+sw+".*/i");
    var ix = undefined;
    
    for(var a=0;a<this.config.options.length;a++){
      if(reAt.test(this.config.options[a].text)){
        ix = a;
        break;
      }
    }
    
    // edit now
    if(ix != undefined){
      if(this.stedix != undefined) jQuery("#"+tg+"_"+this.stedix).removeClass("sted");
      this.stedix = ix;
      jQuery("#"+tg+"_"+ix).addClass("sted");
      jQuery("#"+tg+"_"+ix).scrollToDiv();
    }else{
      if(this.stedix != undefined) jQuery("#"+tg+"_"+this.stedix).removeClass("sted");
      this.stedix = undefined;
    }
  },
  focusMove: function(direction){
    var tg = this.container[0].id;
    if(this.stedix != undefined){
      jQuery("#"+tg+"_"+this.stedix).removeClass("sted");
      if(direction < 0){
        if(this.stedix == 0) this.stedix = this.config.options.length-1;
        else this.stedix += direction;
      }else{
        if(this.stedix == this.config.options.length-1) this.stedix = 0;
        else this.stedix += direction;
      }
    }else{
      this.stedix = 0;
    }
    jQuery("#"+tg+"_"+this.stedix).addClass("sted");
    jQuery("#"+tg+"_"+this.stedix).scrollToDiv();
    jQuery("#"+this.config.inputID).val( this.config.options[this.stedix].text );
  },
  getObject: function(){
    if(this.stedix != undefined){
      return this.config.options[this.stedix];
    }else{
      return {value:"", text:jQuery("#"+this.config.inputID).val()};
    }
  },
  getValue: function(){
    var va = "";
    try{
      va = this.getObject().value;
    }catch(e){
    }
    return va;
  },
  getText: function(){
    var va = "";
    try{
      va = this.getObject().text;
    }catch(e){

    }
    return va;
  },
  nothing: function(){

  }
});